#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time          : 2024/4/30 16:02
# File          : flask_sql_alchemy.py
# @Author       : MingTai
# @Department   : automation_qa
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import not_, or_, and_, desc

app = Flask(__name__)

MYSQL_HOST_2 = "127.0.0.1"
MYSQL_PORT_2 = 3306
MYSQL_USER_2 = "root"
MYSQL_PASSWORD_2 = "123456"
MYSQL_DATABASE_2 = "flask_demo"

# url的格式为：数据库的协议：//用户名：密码@ip地址：端口号（默认可以不写）/数据库名
app.config[
    "SQLALCHEMY_DATABASE_URI"] = f'mysql+pymysql://{MYSQL_USER_2}:{MYSQL_PASSWORD_2}@{MYSQL_HOST_2}:{MYSQL_PORT_2}/{MYSQL_DATABASE_2}'

# # 为了解决控制台的提示
# app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

# 设置每次请求结束后会自动提交数据库的改动
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

# 查询时显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = False

# 创建数据库的操作对象
db = SQLAlchemy(app)


# 创建规则表
class RoleDB(db.Model):
    __tablename__ = "role"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), unique=True)

    # # 增加反查外键关联到UserDB
    # users = db.relationship('UserDB', backref="role")

    # 当调用 Role.query.all() 会触发输出
    def __repr__(self):
        return "Role: %s | %s" % (self.id, self.name)


# 创建用户表
class UserDB(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), unique=True)
    email = db.Column(db.String(32), unique=True)
    password = db.Column(db.String(16))
    role_id = db.Column(db.Integer)

    def to_dict(self):
        """将UserDB实例的信息转换为字典格式，便于进一步的JSON化。"""
        user_data = {
            'id': self.id,
            'name': self.name,
            'email': self.email,
            'password': self.password,  # 注意安全性
            'role_id': self.role_id
        }
        return user_data

    # # 当调用 RoleDB.query.all() 会触发输出
    # def __repr__(self):
    #     return "User: %s | %s | %s | %s" % (self.id, self.name, self.password, self.role_id)


@app.route('/')
def index():
    # 此处查询会走类内 __repr__ 输出
    print("查询所有用户数据: ", UserDB.query.all())
    print("查询所有规则数据: ", RoleDB.query.all())
    print("查询有多少个用户: ", UserDB.query.count())
    print("查询第一个用户: ", UserDB.query.first())

    # 查询过滤器
    print("查询第一条: ", UserDB.query.get(1))
    print("查询过滤器(类名+属性名): ", UserDB.query.filter(UserDB.id == 4).first())
    print("查询过滤器(属性名): ", UserDB.query.filter_by(id=4).first())

    # 查询名字结尾字符为g的所有数据 [开始/包含]
    print(UserDB.query.filter(UserDB.name.endswith("g")).all())
    print(UserDB.query.filter(UserDB.name.contains("g")).all())

    # 查询名字不等于wang的所有数据 [2种方式]
    print(UserDB.query.filter(not_(UserDB.name == "wang")).all())
    print(UserDB.query.filter(UserDB.name != "wang").all())

    #  查询 [名字和邮箱] 都以li开头的所有数据 [2种方式]
    print(UserDB.query.filter(and_(UserDB.name.startswith("li"), UserDB.email.startswith("li"))).all())
    print(UserDB.query.filter(UserDB.name.startswith("li"), UserDB.email.startswith("li")).all())

    # 查询password是 123456 或者 email 以 lyshark.com 结尾的所有数据
    print(UserDB.query.filter(or_(UserDB.password == '123456', UserDB.email.endswith('lyshark.com'))).all())

    # 查询id为 [1, 3, 5, 7, 9] 的用户列表
    print(UserDB.query.filter(UserDB.id.in_([1, 3, 5, 7, 9])).all())
    print(UserDB.query.filter(UserDB.role_id.in_()).all())

    # # 查询name为liu的角色数据：关系引用
    # print(UserDB.query.filter_by(name="liu").first().role.name)

    # 查询所有用户数据 并以邮箱排序 [升序/降序]
    print("升序: ", UserDB.query.order_by("email").all())
    print("降序: ", UserDB.query.order_by(desc("email")).all())

    # 查询第2页的数据,每页只显示3条数据
    # pages = UserDB.query.paginate(2, 3, False)
    # print("查询结果: {} 总页数: {} 当前页数: {}".format(pages.items, pages.pages, pages.page))

    # 完整查询调用写法
    ref = db.session.query(UserDB).filter(UserDB.name == "wang").all()
    print(ref)
    return {
        'msg': 'ok'
    }


# 分页查询
# https://blog.csdn.net/zsx1314lovezyf/article/details/90345688
@app.route("/page/")
def page():
    # 返回的是QueryPagination() 对象（继承Pagination），主要属性
    """
    items: 当前页面中的记录项，是一个模型对象的列表。
    page: 当前页面的页码（整数）。
    per_page: 每页显示的记录项数量。
    prev_num: 前一页的页码。如果当前页是第一页，则为None。
    next_num: 下一页的页码。如果当前页是最后一页，则为None。
    has_prev: 一个布尔值，如果有前一页，则为True，否则为False。
    has_next: 一个布尔值，如果有下一页，则为True，否则为False。
    total: 查询返回的记录总数。
    pages: 总页数。
    query: 返回原始查询对象。
    :return:
    """
    # 无查询条件
    page_no_filter = UserDB.query.paginate(page=1, per_page=3, max_per_page=5)
    # 单个查询条件
    page = UserDB.query.filter(UserDB.role_id == 5).paginate(page=2, per_page=3, max_per_page=5)
    # 多个查询条件
    page_many_filter1 = UserDB.query.filter(UserDB.role_id == 5, UserDB.name == 'zhangsan').paginate(page=1, per_page=3,
                                                                                                     error_out=False)

    page_many_filter2 = UserDB.query.filter(UserDB.role_id == 5) \
                                    .filter(UserDB.name == 'zhangsan').paginate(page=1, per_page=3, error_out=False)

    # 部分查询条件为空的时候
    # 这些条件可能会是None或其他值
    user_id = request.args.get('id', default=None, type=int)
    user_name = request.args.get('name', default=None, type=str)
    user_email = request.args.get('email', default=None, type=str)
    # 基础查询
    query = UserDB.query

    # 根据存在的过滤条件动态添加过滤
    if user_id is not None:
        query = query.filter(UserDB.id == user_id)
    if user_name is not None:
        query = query.filter(UserDB.name == user_name)
    if user_email is not None:
        query = query.filter(UserDB.email == user_email)

    # 应用分页test
    user_pagination = query.paginate(page=1, per_page=2, error_out=False)

    users = []
    for aa in page.items:
        print(aa.to_dict())
        users.append(aa.to_dict())
    print()
    return {
        'total': page.total,
        'page.pages总页码': page.pages,
        'page.page当前页': page.page,
        'data': users

    }


if __name__ == "__main__":
    app.run(debug=True)
